/*
 * LvInput.h
 *
 *  Created on: Sep 29, 2020
 *      Author: fstuffdev
 */

#ifndef LVINPUT_H_
#define LVINPUT_H_

#include <lv_drv_conf.h>
#include "lvglpp.h"

namespace lvglpp
{

	class LvIndev : public lv_indev_t
	{
		LvIndev() = delete;

	public:
		lv_indev_t *raw() noexcept { return this; }
		const lv_indev_t *raw() const noexcept { return this; }

		inline LvIndev &enable(bool en) noexcept { return lv_indev_enable(raw(), en), *this; }

		/**
		 * Get the type of an input device
		 * @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`)
		 */
		inline lv_indev_type_t getType() const noexcept { return lv_indev_get_type(raw()); }

		/**
		 * Reset one or all input devices
		 * @param obj pointer to an object which triggers the reset.
		 */
		inline LvIndev &reset(lv_obj_t *obj) noexcept { return lv_indev_reset(raw(), obj), *this; }

		/**
		 * Reset the long press state of an input device
		 */
		inline LvIndev &resetLongPress() noexcept { return lv_indev_reset_long_press(raw()), *this; }

		/**
		 * Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON)
		 * @param cur_obj pointer to an object to be used as cursor
		 */
		inline LvIndev &setCursor(lv_obj_t *cur_obj) noexcept { return lv_indev_set_cursor(raw(), cur_obj), *this; }

		/**
		 * Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD)
		 * @param group point to a group
		 */
		inline LvIndev &setGroup(lv_group_t *group) noexcept { return lv_indev_set_group(raw(), group), *this; }

		/**
		 * Set the an array of points for LV_INDEV_TYPE_BUTTON.
		 * These points will be assigned to the buttons to press a specific point on the screen
		 * @param group point to a group
		 */
		inline LvIndev &setButtonPoints(const lv_point_t points[]) noexcept { return lv_indev_set_button_points(raw(), points), *this; }

		/**
		 * Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
		 * @param point pointer to a point to store the result
		 */
		inline const LvIndev &getPoint(lv_point_t *point) const noexcept { return lv_indev_get_point(raw(), point), *this; }

		/**
		 * Get the current gesture direct
		 * @return current gesture direct
		 */
		inline lv_dir_t getGestureDir() const noexcept { return lv_indev_get_gesture_dir(raw()); }

		/**
		 * Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD)
		 * @return the last pressed key (0 on error)
		 */
		inline uint32_t getKey() const noexcept { return lv_indev_get_key(raw()); }

		/**
		 * Check the current scroll direction of an input device (for LV_INDEV_TYPE_POINTER and
		 * LV_INDEV_TYPE_BUTTON)
		 * @return LV_DIR_NONE: no scrolling now
		 *         LV_DIR_HOR/VER
		 */
		inline lv_dir_t getScrollDir() const noexcept { return lv_indev_get_scroll_dir(raw()); }

		/**
		 * Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and
		 * LV_INDEV_TYPE_BUTTON)
		 * @return pointer to the currently scrolled object or NULL if no scrolling by this indev
		 */
		inline lv_obj_t *getScrollObj() const noexcept { return lv_indev_get_scroll_obj(raw()); }

		/**
		 * Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and
		 * LV_INDEV_TYPE_BUTTON)
		 * @param point pointer to a point to store the types.pointer.vector
		 */
		inline const LvIndev &getVect(lv_point_t *point) const noexcept { return lv_indev_get_vect(raw(), point), *this; }

		/**
		 * Do nothing until the next release
		 */
		inline LvIndev &waitRelease() noexcept { return lv_indev_wait_release(raw()), *this; }

	public:
		/**
		 * Get the currently processed input device. Can be used in action functions too.
		 * @return pointer to the currently processed input device or NULL if no input device processing
		 * right now
		 */
		static inline LvIndev *getAct(void) noexcept { return (LvIndev *)lv_indev_get_act(); }

		/**
		 * Gets a pointer to the currently active object in the currently processed input device.
		 * @return pointer to currently active object or NULL if no active object
		 */
		static inline lv_obj_t *getObjAct(void) noexcept { return lv_indev_get_obj_act(); }

		/**
		 * Get a pointer to the indev read timer to
		 * modify its parameters with `lv_timer_...` functions.
		 * @return pointer to the indev read refresher timer. (NULL on error)
		 */
		static inline lv_timer_t *getReadTimer(lv_disp_t *indev) noexcept { return lv_indev_get_read_timer(indev); }

		/**
		 * Search the most top, clickable object by a point
		 * @param obj pointer to a start object, typically the screen
		 * @param point pointer to a point for searching the most top child
		 * @return pointer to the found object or NULL if there was no suitable object
		 */
		static inline lv_obj_t *searchObj(lv_obj_t *obj, lv_point_t *point) noexcept { return lv_indev_search_obj(obj, point); }
	};

} // namespace lvglpp

#endif /* LVINPUT_H_ */
